04/22/95 Recompiled the sample Application, GTERM, to be compatible with the Clarion For DOS 3.1 Template set. Some minor changes to a couple of Source Modules were required. No changes to CLACom itself were necessary to be compatible with 3.1. It should be noted that the GTERM sample application will no longer work or load under 3.0. This is not true of CLACom itself. Only the sample application. The GTERM sample application now includes a script language. The retail version of CLACom includes the "C" module that drives the Script engine, for those that would like to see how it is implemented. The Script Language is described in the File SCRIPT.TXT (in the GTERM directory). A sample script file is also included. The Script "engine" is contained in 2 modules. One of them is a Clarion Source Procedure in GTERM. The other is a "C" language module inside of ???SCRPT.LIB. The "C" module contains the low level routines that are just not suitable for the Clarion language, however they could no doubt be re-written entirely in Clarion. Adding a Script Language to GTERM shows how application dependent such a language is. GTERM is now literally sprinkled with Script dependent variables. It is continuosly checking to see if it is being driven by a script. If you study the GTERM source code, you will see how it would be virtually impossible to include a generic script language in CLACom itself. 03/06/95 A new variable has been added that allows you to tell SetPort() to NOT check for the presense of a UART. To use it add the following to your global data declarations: nochkport SHORT,EXTERNAL,NAME('nochkport') Setting nochkport to 1 will bypass the UART checking routines, and should only be so set if SetPort is telling you there is no UART installed and you know that there is, in fact, a UART at the Base Address for the Port. A new function has been added that allows you to retrieve a block of characters from the Serial Port. It is similar to ComGetB except that you tell it how many characters to retrieve. It is Prototyped as follows: ComGetBlock(SHORT,*CSTRING,SHORT),SHORT,PASCAL,RAW,NAME('COMGETBLOCK') ComGetBlock ----------------------------------------------------------------- Purpose Retrieve a Block of Characters ComGetBlock(port,buf,num) SHORT port COM Port Number CSTRING buf Buffer to store characters in SHORT num Number of characters to retrieve Type Function - Returns SHORT Description This function will retrieve a block of characters from the Receive Buffer. It is similar to ComGetB except that in this case, you tell it how many characters to retrieve. If the requested number of characters are not available (meaning, there are fewer characters in the Receive Buffer than what you are requesting) the function will return 0 and not take any charac- ters out of the Receive Buffer. Otherwise the return value will be the same as the number of characters you have requested. Note that this function will not work with the Interrupt 14 Interface. Return Value # of Characters stored in your Buffer, or 0 if the Requested Number of Characters are not available. Example retcode SHORT ComPort SHORT cstr CSTRING(100) ComPort = 0 ! use COM 1 ! Get a Block of 20 characters retcode = ComGetBlock(ComPort,cstr,20) 01/29/95 For those running fast computers with slow UARTS, CLACom will now "slow down" when you call SetPort() and it tries to determine if a UART is actually installed at the Base Port address. Our computers, now days, are much faster than the UARTS. When we write to a UART Register and then immediately re-Read that same Register, we must do so with a minor delay between the "write" and the "read". CLACom now does this when it checks to see if there is a UART installed at a specified port. InitPort() will now return an error code of 1 if SetPort() was not called ahead of time to Set Up the COM Port. This is per the manual which said it would do this. InitPort was returning an error code of 2, meaning "Invalid Parameter" if the COM port was not first initialized. InitPort() was seeing the COM port Parameter as "invalid" if SetPort() had not been called previously to initialize that specific COM Port. The manual says it will return an error code of 1 in this case, and InitPort() now does so. 01/07/95 Crash Recovery on Zmodem Receives has been implemented (it has always been implemented on Sends). Crash Recovery means that CLACom will NOT delete a file if the transfer is aborted for whatever reason. The partial file will remain in the directory to allow the end user to attempt the download at a later date. At such a later time, CLACom will instruct the sending Zmodem to begin the transfer where the last one left off. Crash Recovery is ON, by default. To disable it (for instance, a BBS program would not want partial files to remain in its upload directory), add the following to your global data declarations: zcrash SHORT,EXTERNAL,NAME('_zcrash') ! 0 = delete receive file ! if error Set 'zcrash' to 0 to disable Zmodem Crash Recovery. A new Communications Port Interface has been added. It is a basic Interrupt 14 Interface that uses the 4 BIOS Interrupt 14 functions. The highest Baud Rate supported is 9600 bps, and even at that speed, you are likely to loose characters if the Interrupt 14 handler doesn't have its own receive buffers or if the attached modem does not use Hardware flow control and does not contain its own internal buffers. COM Ports are limited to COM 1 and COM 2 (which are zero based, COM 1 = 0, COM 2 = 1), although some Interrupt 14 BIOS replacements allow for higher port numbers, and if so, they may be used. Note that many of the Communications Routines will not work with this interface. Particularly, any routine that clears a buffer, peeks at the receive buffer, or attempts to manipulate the Modem or Line Status Registers (DTR(), RTS(), etc). If you attempt to call one of these functions while using the Interrupt 14 Interface, they will simply return without doing anything. Zmodem will NOT work with this Interface if the Interrupt 14 driver does not buffer received data (which is the case if using the computer BIOS routines). You are limited to 4 very basic functions: Initialize the Port Send a character Read a character Retrieve Modem Status You may also use any of the CLACom functions that send strings such as ComPuts() and ModemPuts() or any function that relies upon one of the 4 basic Interrupt 14 calls. GTERM has been updated to show a real world example of the new Interface. Three new functions were added to support the Interrupt 14 Interface: Inside your CLACOM.MAP (CLACOM.INC) Int14SetPort(SHORT),SHORT,PASCAL,NAME('INT14_SETPORT') Int14ResetPort(SHORT),PASCAL,NAME('INT14_RESETPORT') Int14InitPort(SHORT,LONG,SHORT,SHORT,SHORT),SHORT,PASCAL,NAME('INT14_INITPORT') Function Reference for New Features Int14SetPort ----------------------------------------------------------------- Purpose Sets up variables in preparation for Interrupt 14 I/O Int14SetPort(port) SHORT port COM Port Number Type Function - Returns SHORT Description This function simply sets internal variables that inform the Communications Routines to use the Interrupt 14 I/O functions. This function MUST be called prior to using any of the other Communications Routines. Return Value Always returns 0. Example keychr BYTE retcode SHORT ComPort SHORT ComPort = 0 ! use COM 1 retcode = Int14SetPort(ComPort) ! Initialize for INT 14 ! Set COM 1 to 2400, 8, N, 1 retcode = Int14InitPort(ComPort,2400,0,8,1) Loop If GetKeyc() = 27 ! Check for ESC Key Break End retcode = ComGetc(ComPort) ! anything from remote? If retcode NOT= -1 ! yes keychr = retcode ! translate to Byte Value Gputc(keychr) ! and display End End Int14InitPort ----------------------------------------------------------------- Purpose Initializes Port to Baud, Parity, Data, and Stop Int14InitPort(port,baud,parity,data,stop) SHORT port COM Port Number (0 based) LONG baud Baud Rate SHORT parity 0 = None, 1 = Odd, 2 = Even SHORT data 6, 7, or 8 SHORT stop 1 or 2 Type Function - Returns SHORT Description Initializes the Serial Port to the specified Baud Rate, Parity, Data bits, and Stop bits. The Baud Rate is limited to 9600 bps. The Computer BIOS supports COM 1 and COM 2 only. If your end users will be using an Interrupt 14 BIOS replacement handler, they may use whatever COM ports that handler supports. Return Value 0 for success or 1 for bad parameter Example keychr BYTE retcode SHORT ComPort SHORT ComPort = 0 ! use COM 1 retcode = Int14SetPort(ComPort) ! Initialize for INT 14 ! Set COM 1 to 2400, 8, N, 1 retcode = Int14InitPort(ComPort,2400,0,8,1) Int14ResetPort ----------------------------------------------------------------- Purpose Tells COM routines we are finished with Port Int14ResetPort(port) SHORT port COM Port Number (0 based) Type Procedure Description This function resets internal variables and dis- ables use of the Interrupt 14 I/O calls. It is provided for compatibility and is not really needed. Return Value None. Example port SHORT port = 0 ! use COM 1 Int14ResetPort(port) ! Tell COM I/O were done 01/03/95 CLACom is now "Multi-Tasking Aware". This means that while awaiting KeyBoard or COM Port Input, if there are no characters from the local keyboard or the COM Port, you can tell CLACom to give up your program's Time Slice to other processes. It is also possible to give up your program's Time Slice while in an ACCEPT or ASK Loop, providing you "hook" the ACCEPT or ASK with an IDLE Procedure and you call DVPause() at the end of your IDLE Procedure. If you use the KeyBoard() function, you can add functionality to the KeyBoard() Loop without adding an IDLE Procedure. See example for DVPause(). CLACom will automatically give up your Program's Time Slice while it is waiting for CTS to become active (providing you make a call to DVHere() at the beginning of your program). When dealing with Modems, CTS can become inactive for 1 to 10 seconds if you are using a High Speed Modem and the other modem is connected at less than your DTE bps rate (IE, you have your COM Port set to 57,600 and you are connected to a remote device that is talking to your modem at 1200 bps). Two new functions and 1 new variable were added to support the Multi-Tasking Aware features: Inside your CLACOM.MAP (CLACOM.INC) DVHere(),SHORT,PASCAL,NAME('DV_HERE') DVPause(),PASCAL,NAME('DV_PAUSE') Inside your Global Data Declarations gotdv SHORT,EXTERNAL,NAME('_gotdv') DVHere() should be called at the very beginning of your program. Its purpose is to determine if your program is running under a Multi-Tasker. If so, it will set the 'gotdv' flag to one of the following: 0 - No Multi-Tasker Detected 1 - DESQView 2 - Windows Enhanced Mode 3 - OS/2 ver 2.0 4 - OS/2 ver 2.1x Feel free to call this function during your program's initialization. It is not necessary that any other CLACom routines be called ahead of time. This function ONLY SETS the 'gotdv' flag. It simply tries to determine if your program is running under DESQView, Windows, or OS/2. The Return Value is the same as the 'gotdv' flag. After calling this function, you may test either the return value or the 'gotdv' flag to determine if you need to give up your Time Slices during KeyBoard and COM I/O Loops. DVPause() is the Procedure that actually does all the work in making sure your program is Multi-Tasking "aware". It checks the 'gotdv' flag and if it isn't set, it simply returns. If the flag IS set, it gives up the rest of your program's Time-Slice and it will not return until your next scheduled Time-Slice (this effectively puts your program to sleep for the duration of your allocated "slice of the clock tics"). DVPause() should be used in all loops that "do nothing". That is, if you are waiting for something to do, such as input from the local KeyBoard, input from the COM Port, you should call this procedure if there is no input to process (no key presses and no characters arriving at the COM Port). Clarion's KeyBoard() function and CLACom's RxEmtpy() function are two likely candidates for LOOPS that can use DVPause(). If you are in an ACCEPT or ASK Loop, you can set up an IDLE Procedure to more or less force Clarion to become Multi-Tasking Aware. Function Reference for New Features DVHere ----------------------------------------------------------------- Purpose Checks to see if running under a Multi-Tasker DVHere() Type Function - Returns SHORT Description This function will check to see if your program is running under DESQView, Windows, or OS/2. Return Value 0 if no Multi-Tasker Detected otherwise: 1 - DESQView 2 - Windows Enhanced Mode 3 - OS/2 ver 2.0 4 - OS/2 ver 2.1x Example MultiTasker SHORT MultiTasker = DVHere() ! running under MultiTasker? DVPause ----------------------------------------------------------------- Purpose Gives up Time Slice to Multi-Tasker DVPause() Type Procedure Description If your program is running under a Multi-Tasker, calling this procedure will give up the rest of your Time Slice to other tasks that are running. To check if your program is running under a Multi- Tasker, you can either check the return value from DVHere() or the global variable _gotdv (_gotdv is set after making a call to DVHere). You must first make a call to DVHere(), preferably at the very beginning of your program. DVHere() sets the appropriate flags that this Procedure looks for. You need to call DVHere() once only. DVPause() is then used inside of all KeyBoard and COM Input Loops. Return Value None Example MultiTasker SHORT MultiTasker = DVHere() ! running under MultiTasker? While Rxempty(0) ! nothing from COM Port If KeyBoard() ! got a local Key Press break ! handle it End ! At this point, there is nothing coming in from the COM ! Port and nothing happening at the Local KeyBoard. ! So, we will check to see if we are running under a ! Multi-Tasker, and if so, give up our Time Slice (since ! we aren't doing anything at this point except for wasting ! Clock Tics) If MultiTasker ! if running under a DVPause() ! Multi-Tasker, then give End ! up Time Slice End 11/15/94 The functionality of the 'noascmes' variable has been changed when Sending files using the ASCII Upload File Transfer function. When uploading files, and if this variable is set to 1, the ASCII Upload function will NOT display incomming characters on the screen. Generally when Uploading Files using ASCII, the Receiver sends each character back to you. The standard procedure for ASCII Uploads is to remove these characters out of the Receive Buffer and display them on the Screen. This is the standard behavior for CLACom's ASCII Upload function. Some of you, however, are using ASCII Uploads to transfer information to other computers, rather than as an actual File Transfer Protocol. In such cases, you don't want CLACom removing characters out of the Receive Buffer, much less displaying them on the screen. Note that the receiver must be set to NOT echo the characters you send it, back to you. Otherwise, your Receive buffer will likely fill up if you send a great deal of data, and you have 'noascmes' set to 1. If you haven't already done so, you must declare the 'noascmes' variable as an External Short, in order to access it: noascmes SHORT,EXTERNAL,NAME('noascmes') 09/14/94 A new variable has been added. You may use it to tell the File Transfer Routines to NOT check for carrier. If set to a non zero value, the File Transfer Routines will ignore the state of Carrier Detect. The variable should be defined in your Clarion Application as follows: NoChkCar SHORT,EXTERNAL,NAME('nochkcar') 06/20/94 WARNING!!! ---------- Because of numerous requests, when using your own File Transfer Progress Screen - passing a 1 for the last parameter to the following functions: Download, Upload, GetZmodem, SendZmodem, and SendZmodem1 CLACom will now CALL a user supplied function that is responsible for updating the screen. Previously, CLACom would simply call the Clarion Display() procedure to update your screen. The procedure that CLACom will call is named UpdXferScreen. Because of this change, you must write this routine and include it as part of any application that uses CLACom. You must do this even if you use the built in File Transfer Progress Screen. Because Clarion does not support a pointer data type, we had to hard code this procedure name into the file transfer routines. This procedure can simply contain a single line that calls the Display() procedure, or it can tally upload or download statistics. The sample application shows how to declare the UpdXferScreen, when to Open and Close it, and how to update it with the current transfer statistics. Do not forget to add the UpdXferScreen procedure to your applications or you will receive an "unresolved reference" when linking. A new Communications Interface has been added. The new interface is Fossil. To use the Fossil Interface your users must have a Fossil Driver loaded. The best Fossil Driver to use is X00.SYS, as it provides more features and faster communications. The following new functions are specific to the Fossil Interface: FosSetPort ----------------------------------------------------------------- Purpose Tells the Fossil Driver to give us the Port. FosSetPort(port) SHORT port COM Port Number (0 based) Type Function - Returns SHORT Description This function simply tells the Fossil Driver that you wish to use the specified Port. Return Value 0 for success or 1 if Fossil Driver not loaded. Example port SHORT port = 0 ! use COM 1 If FosSetPort(port) ! Tell Fossil we want Port ! Display Fossil Driver Not loaded Error End FosInitPort ----------------------------------------------------------------- Purpose Initialize Fossil Port to baud, data, parity and stop. FosInitPort(port,baud,parity,data,stop) SHORT port COM Port Number (0 based) LONG baud Baud Rate SHORT parity 0 = None, 1 = Odd, 2 = Even SHORT data 6, 7, or 8 SHORT stop 1 or 2 Type Function - Returns SHORT Description Initializes the Fossil Port to the specified Baud Rate, Parity, Data bits, and Stop bits. If the user is not using X00.SYS, the Baud Rate is limited to 38,400 bps. Due to the limitation of the Interrupt 14 interface that is used by Fossil Drivers, the highest Baud Rate that can be set via this function is 38,400 bps. However, users can set a higher Baud Rate when loading the Fossil Driver. If the user wishes to use a rate higher than 38,400 bps, the user must tell the Fossil Driver to "lock" the Baud Rate. Your program will still be limited to 38,400 bps, however, the Fossil Driver (when locked) will ignore any requests to change the Baud Rate. Return Value 0 for success or 1 for bad parameter Example port SHORT port = 0 ! use COM 1 ! initialize COM 1 to 38400, 8 N 1 retcode = FosInitPort(port,38400,0,8,1) FosResetPort ----------------------------------------------------------------- Purpose Tells the Fossil Driver we are finished with Port. FosResetPort(port) SHORT port COM Port Number (0 based) Type Procedure Description This function tells the Fossil Driver that you are finished with the specified Port. Return Value None. Example port SHORT port = 0 ! use COM 1 FosResetPort(port) ! Tell Fossil were done FosClrTx ----------------------------------------------------------------- Purpose Clears the Fossil Transmit Buffer FosClrTx(port) SHORT port COM Port Number (0 based) Type Procedure Description Clears the Transmit Buffer for the Fossil Port. Return Value None Example port SHORT port = 0 ! use COM 1 FosClrTx(port) ! Flush Xmit Buffer FosSetPort must be called before using any of the other Communications routines. The Standard Interface (internal, high speed, Interrupt driven interface) now supports up to 8 simultaneous ports and higher IRQ's. You are now free to use IRQ's 2 - 15. The PeekChr function now returns the position in the Receive Buffer where the character was found. Two new functions were added to the Standard Interface. These are PeekStr and ComClrToStr. PeekStr is similar to PeekChr except that it searches for a string instead of a single character. ComClrToStr will clear the Receive Buffer up to and including a specified string. The manual pages for these functions are presented below: PeekStr ----------------------------------------------------------------- Purpose Search for specified string PeekStr(port,str) SHORT port COM Port Number CSTRING str String to search for Type Function - Returns SHORT Description This function will search the Receive Buffer for the specfied string. Return Value 0 if string not in buffer or position in buffer where the string starts. If there is an error allo- cating memory, a -1 will be returned. Example port SHORT retchr SHORT str CSTRING(80) port = 0 ! use COM 1 str = 'Phone' ! look for this If PeekStr(port,str) > 0 ! if string is there retchr = ComClrToStr(port,str) ! eat characters up to End ! and including string ComClrToStr ----------------------------------------------------------------- Purpose Clears buffer up to and including string ComClrToStr(port,str) SHORT port COM Port Number CSTRING str String to use as delimiter Type Function - Returns SHORT Description This function will clear the Receive Buffer of any characters up to and including the passed string. All characters prior to the string are removed from the buffer, then the string itself is removed. Return Value 0 if buffer was cleared, 1 if string not there or buffer is empty, 2 if error allocating memory. Example port SHORT retchr SHORT str CSTRING(80) port = 0 ! use COM 1 str = 'Phone' ! look for this If PeekStr(port,str) > 0 ! if string is there retchr = ComClrToStr(port,str) ! eat characters up to End ! and including string 03/25/94 Changes were made to the Upload and Download routines. They take a parameter which tells them whether they should use the internal Transfer Progress Screen or update a Progress Screen that you display yourself. The function affected are: Download, Upload, GetZmodem, SendZmodem, and SendZmodem1 You will need to modify your Clarion code so that the new parameter is passed to each of these functions. The sample application shows how to set up and display your own Progress Screen. Several new functions and variables have been added or documented. Rather than explain the changes individually, we will provide the relevant manual pages below. Overlays - Protected Mode You must perform one final step before generating your CLACOM application. The Standard Communications interface takes over the interrupt vector for the selected COM Port. This means that the interrupt service routine can not be swapped out. It must remain in memory at all times. The same is true if you enable the Ctrl-Break intercept routine (which you should). In order to keep the Communications routines in memory and prevent them from being swapped out, you must create a file that is used by the Project System to determine how segments are loaded. In your Clarion directory is a file called ROVERLAY.EXP. Copy this file to your application's directory, renaming it in the process by giving it the same base name as your application and with an .EXP extension. Next, edit the file and add the following lines to the end of the SEGMENTS section: GCOM_DATA PRELOAD FIXED GCOM_TEXT PRELOAD FIXED A portion of the Export File would appear as follows: CLAICEP_TEXT PRELOAD CLAFIXED_DATA PRELOAD GCOM_DATA PRELOAD FIXED GCOM_TEXT PRELOAD FIXED Please do not take the above change lightly or forget to make it. Failure to add the above lines will cause your program to crash as soon as the communications routines are swapped out of memory. This is especially important for Protected Mode programs as you want the Communications routines to remain FIXED in memory. Be sure to name this file correctly or the Project System will not use it. Its base name (the first 8 characters) is the same as your application's base name. Its 3 character extension is "EXP". For instance, in the GTERM sample application, the name of its Export File is GTERM.EXP. If your Overlayed or Protected Mode application locks up the computer, causes an XTRACE, or causes an Exception Error, and you can attribute the problem to CLACOM, check your application's directory for the presence of the Export File and make sure it contains the correct 2 lines as discussed above. File Transfers CLACOM supports all of the popular File Transfer Protocols. Each of the protocols are given a number (with the exception of Zmodem). Before initiating an Upload or a Download, you need to prompt the user for a Protocol. Your end users won't be the least bit impressed about having to type in a number so your Protocol Browse Box should display Protocol Names. In the background, you will translate the Names into numbers to send to the protocol drivers. The sample Terminal Program shows an excellent example of how to prompt for a Protocol and translate the string into a number to send to the protocol drivers. The Protocols are numbered as follows: 0 - ASCII 3 - 1K Xmodem-G 1 - Xmodem 4 - Ymodem 2 - 1K Xmodem 5 - Ymodem-G Note that as far as CLACOM is concerned, there is no difference between Checksum Xmodem and CRC Xmodem. CLACOM always starts in "CRC Mode" but will adjust itself as necessary. Also note that both of the Ymodem protocols (as well as Zmodem) are Batch Protocols and when Downloading, you need not prompt for a File Name since the name will be supplied by the sender. When Uploading you can either provide a single File Name to upload or a Wild Card specification. To Download (receive) files using the above protocols, you call the DownLoad function. The equivalent Zmodem function is called GetZmodem. To Upload (send) files using the above protocols, you call the UpLoad function. The equivalent Zmodem function is called SendZmodem or SendZmodem1. When transferring files you have two options when displaying the transfer statistics (i.e., the CPS rating, bytes transferred, progress meter, etc.). You can use the built in Transfer Statistics Window or display your own window. The built in window may not be suitable for some applications. For instance, you may not like its colors or its screen position. To use your own Transfer Statistics Window, simply pass the value of 1 in the statfunc parameter when calling the Upload or Download functions. When using your own window, the file transfer statistics will be displayed according to how you design the screen. You may display some or all of the statistics. Because Clarion does not have a pointer data type, the transfer functions cannot call your procedure so that you may keep track of your own statistics. Instead, all they can do is update your transfer window. This means that your screen structure will need to be designed so that it uses the variables that the transfer functions use to keep track of the statistics. These variables are all of the CSTRING data type and are usable by your Clarion application simply by declaring a GROUP structure over the first variable. To utilize these variables in your screen structure, declare a GROUP structure as follows: TransferVars GROUP, PRE(XFR), EXTERNAL, NAME('xfervars') FileName CSTRING(128) ! File Name FileSize CSTRING(14) ! Size of File Blocks CSTRING(8) ! # of Blocks in File Bytes CSTRING(10) ! # of Bytes in File Errors CSTRING(8) ! Current errors CPS CSTRING(10) ! Current CPS Rating StatusMes CSTRING(26) ! Current Status Message Protocol CSTRING(14) ! Current Protocol StatMeter CSTRING(34) ! Progress Meter End You will probably have to code the screen structure by hand since Clarion does not allow you to select global variables for use in screen fields. You can use the screen structure in the sample application as a template for your own screens. To reference the transfer statistics variables, you declare an ENTRY field with the SKIP attribute using one of the above variable names: XFERSCREEN SCREEN(12,60),PRE(XSC),CENTER,SHADOW,COLOR(30) ROW(2,4) STRING('File Name :') .......... ROW(5,7) STRING('Blocks :') .......... ROW(8,7) STRING('Status :') ROW(2,16) ENTRY(@S14),USE(XFR:FileName),SKIP,COLOR(63,78,120) ROW(5,16) ENTRY(@S8),USE(XFR:Blocks),SKIP,COLOR(63,78,120) ROW(8,16) ENTRY(@S26),USE(XFR:StatusMes),SKIP,COLOR(63,78,120) End. Prior to calling an Upload or Download function you should open your transfer screen. When the file transfer is completed, you should then close your screen. The transfer routines will update your screen after each block of data is sent or received (this is the equivalent to you calling the Clarion Display procedure). Note that when using your own transfer window, if there is a critical error such as the inability to open the file, no error message will be displayed. You should check the return code from the transfer functions and display your own error message if necessary. When Downloading (receiving) files, the files will be placed into the current working directory. If you want the files to be placed into a specific directory, you should change into that directory prior to calling a Download function. When Uploading (sending) files, the files are expected to be in the current working directory. You need to change into whatever directory the files are located in. One exception to this is Zmodem where there is an alternate Send function that allows you to pass the directory path as one of the parameters (please see SendZmodem1 in the Reference Section for more information about this function). Capture Buffers CLACOM supports automatic Scroll Back or Capture Buffers. When enabled, any data (with the exception of ANSI sequences) that is sent to the ANSI driver using Gputs or Gputc is also placed in the capture buffer. The capture buffer is capable of holding 64k of data and is automatically written to disk when it becomes full. After a disk write, the buffer is reset so that another 64k of data can be stored. Two functions are provided to support capturing of data. SetCaptureFile tells the capture routines what name to give the capture file. It should be called first. If you do not call this procedure then a default name will be used for the capture file. SetCapture is used to turn the capture buffer on or off. You must always be sure to call SetCapture with a parameter of 0 to turn the capture buffer off when you are finished with the capture file. Failure to do so will leave the buffer memory allocated and will prevent flushing the capture data to disk (whatever is in the buffer will be lost). CLACOM is responsible for capturing and saving the data. What you do with the data is up to your application. If you would like for your users to be able to view the data, you will need to provide Clarion routines for doing so. If you do provide a View procedure to allow your users to view the capture data, be sure to first call SetCapture with a parameter of 0 to flush the capture buffer to disk. When you regain control from the View procedure, you will once again need to call SetCapture with a parameter 1 to turn the capture buffer back on. The following is an example of using a capture buffer: ScrFile CSTRING(64) ! Name of ScrollBack File ! set up an automatic Scroll Back Buffer ScrFile = 'GTERM$$.CAP' ! Give Scroll File a name Do TurnOnCapture ! Turn on Capture ..... ! your program code here ! end of procedure, close Scroll Back Buffer retchr = SetCapture(0) ! Turn Capture Off Return ! Return from Procedure TurnOnCapture Routine ! Turn on Capture SetCaptureFile(ScrFile) ! Tell Capture File Name if SetCapture(1) ! and turn on Capture Open(CaptureErr) ! couldn't allocate Mem bell() ! make noise Accept ! tell um Close(CaptureErr) ! close error screen end Exit ! Return from Routine GTERM gives an excellent example of how to utilize an automatic Scroll Back buffer and allow the user to specify a Capture Buffer. It also shows how to allow the user to view the contents of the Scroll Back or the Capture Buffer, clear the buffer, and save it under a different name. Global Variables The following variables are declared global and may be used by your application to alter the behavior of the Communications routines. The names shown are the actual names used by the Communications routines. See the sample application to see how they are declared and named: asciidel The number of clock tics to delay after sending each line in a file when using the ASCII file transfer. 18 tics equals 1 second. combufsiz Sets the size of the Receive Buffer when using the Direct Interface. The Receive Buffer defaults to 6144 bytes. This has proven to be the optimal size for high speed communications when using a file transfer protocol such as Ymodem-G. However you may increase or decrease this size by changing this variable (decreasing the size will typically result in lost data at high speeds). crscur Contains the ANSI driver's current Cursor Position. The high byte contains the row coordinates and the low byte contains the column coordinates. Changing this variable changes the cursor position. gnormal Contains the ANSI driver's current Color. This is the initial color that you pass to InitAnsi but it will change whenever an ANSI color sequence is sent to Gputs or Gputc. Changing this variable changes the color of subsequent characters sent to the ANSI driver. gotdv Normally set to 0. After a call to DVHere(), it will contain the following values: 0 - No Multi-Tasker Detected 1 - DESQView 2 - Windows Enhanced Mode 3 - OS/2 ver 2.0 4 - OS/2 ver 2.1x This variable is tested by programs that need to provide better performance when running under a Multi-Tasker. meterchr This variable defines the character that makes up the Progress Meter on the File Transfer Status Window. noascmes When set to 1, disables all messages and windows associated with ASCII file transfers. This is useful when you are using the ASCII upload/download routines for something other than transferring files. nocts When set to 1, disables the Clear To Send (CTS) checking that is performed by the Communications Output routines. Should never be set unless there is a specific reason for doing so. usefifo If a Communications Port has a 16550 UART installed, the FIFO buffers on the UART will automatically be turned on and utilized. Some UART chips have defective FIFO implementations where turning on the FIFO buffers will cause incorrect behavior. To disable the FIFO buffers, set this flag to 0. Function Reference ComGetb ----------------------------------------------------------------- Purpose Retrieves all the characters in the Receive Buffer. ComGetb(port, str) SHORT port COM Port Number CSTRING str String to store characters in Type Function - Returns SHORT Description Retrieves all of the characters in the Receive Buffer and stores them in the passed string. If a 0 is returned, it means the Reveive Buffer was empty. In this case, a NULL string will be returned. The string passed to this function must be of sufficient length to hold all of the characters. It is very easy to overwrite code or data with this function if the passed string parameter is not large enough to hold all of the data. Return Value 0 or the number of characters stored in the passed string. Example port SHORT numbytes SHORT cstr CSTRING(255) port = 0 ! use COM 1 numbytes = ComGetb(port,cstr) ! get the string ComGets ----------------------------------------------------------------- Purpose Gets a string of characters up to terminator. ComGets(port, str, chr) SHORT port COM Port Number CSTRING str String to store characters in BYTE chr Character to look for Type Function - Returns SHORT Description Retrieves a string of characters up to, but not including, the terminating character. The characters are stored in the string that you pass as a parameter. Characters are stored until the terminator is encountered. If a 0 is returned, it means the terminator was the first character in the Receive Buffer. In this case, a NULL string will be returned. This function does not time out. It will not return until it encounters the terminator. Unless you know for a fact that the terminating character is in the Receive Buffer, you should call PeekChr first to make certain that the terminating character is in the buffer. The string passed to this function must be of sufficient length to hold all of the characters that are stored while looking for the terminator. It is very easy to overwrite code or data with this function if the passed string parameter is not large enough to hold all of the data. Return Value 0 or the number of characters stored in the passed string. Example port SHORT numbytes SHORT cstr CSTRING(255) port = 0 ! use COM 1 if PeekChr(port,10) ! check for Line Feed numbytes = ComGets(port,cstr,10) ! get the string end DownLoad ----------------------------------------------------------------- Purpose Receives one or more files. DownLoad(port, protocol, filename, statfunc) SHORT port COM Port Number SHORT protocol Number of protocol to use CSTRING filename Name of file to download SHORT statfunc 0 or 1 (see below) Type Function - Returns SHORT Description This function allows you to receive a file from a remote computer. The protocols are defined as follows: 0 = ASCII 3 = 1K Xmodem-G 1 = Xmodem 4 = Ymodem 2 = 1K Xmodem 5 = Ymodem-G Filename is a CSTRING containing the name of the file to download. If the protocol is a batch protocol (Ymodem or Ymodem-G) then you may pass a NULL string (cstr = '') since the name of the file will be supplied by the remote sender. If a filename is passed, it will be ignored. The statfunc parameter allows you to override the default Transfer Status Window. A value of 0 means the internal window will be displayed and updated. A value of 1 means you will open your own window and the transfer statistics will be displayed on it instead. Return Value 0 for successful transfer. If an error occurs, the following values are returned: 1 - Error opening file 6 - Error writing file 2 - Receiver cancelled 7 - CRC error (1K Xmodem-G 3 - Sender cancelled or Ymodem-G) 4 - Time out 8 - Too many errors 5 - No carrier 9 - Block error Example cstr CSTRING(100) cstr = 'FILE.ZIP' ! receive a single file DownLoad(0,2,cstr,0) ! using 1K Xmodem cstr = '' ! receive 1 or more files DownLoad(0,4,cstr,0) ! using Ymodem DVHere ----------------------------------------------------------------- Purpose Checks to see if running under a Multi-Tasker DVHere() Type Function - Returns SHORT Description This function will check to see if your program is running under DESQView, Windows, or OS/2. Return Value 0 if no Multi-Tasker Detected otherwise: 1 - DESQView 2 - Windows Enhanced Mode 3 - OS/2 ver 2.0 4 - OS/2 ver 2.1x Example MultiTasker SHORT MultiTasker = DVHere() ! running under MultiTasker? DVPause ----------------------------------------------------------------- Purpose Gives up Time Slice to Multi-Tasker DVPause() Type Procedure Description If your program is running under a Multi-Tasker, calling this procedure will give up the rest of your Time Slice to other tasks that are running. To check if your program is running under a Multi- Tasker, you can either check the return value from DVHere() or the global variable _gotdv (_gotdv is set after making a call to DVHere). You must first make a call to DVHere(), preferably at the very beginning of your program. DVHere() sets the appropriate flags that this Procedure looks for. You need to call DVHere() once only. DVPause() is then used inside of all KeyBoard and COM Input Loops. Return Value None Example MultiTasker SHORT MultiTasker = DVHere() ! running under MultiTasker? While Rxempty(0) ! nothing from COM Port If KeyBoard() ! got a local Key Press break ! handle it End ! At this point, there is nothing coming in from the COM ! Port and nothing happening at the Local KeyBoard. ! So, we will check to see if we are running under a ! Multi-Tasker, and if so, give up our Time Slice (since ! we aren't doing anything at this point except for wasting ! Clock Tics) If MultiTasker ! if running under a DVPause() ! Multi-Tasker, then give End ! up Time Slice End GetCRC16 ----------------------------------------------------------------- Purpose Returns a 16 bit CRC. GetCRC16(crc, value) SHORT crc Current CRC SHORT value Vaule to add to CRC Type Function - Returns SHORT Description This is an internal function used by the File Transfer routines to calculate the 16 bit CRC of a data block. To use, you first set the initial CRC value to 0. Then for each character (typically a data buffer) you pass the current CRC value and the character for which you wish to obtain a CRC from. Return Value 16 Bit CRC value. Example crc16 SHORT value SHORT crc16 = 0 ! Initialize crc16 = GetCRC16(crc16,value) ! get CRC GetCRC32 ----------------------------------------------------------------- Purpose Returns a 32 bit CRC. GetCRC32(value,crc) SHORT value Vaule to add to CRC LONG crc Current CRC Type Function - Returns LONG Description This is an internal function used by the Zmodem Transfer routines to calculate the 32 bit CRC of a data block. To use, you first set the initial CRC value to 0FFFFFFFF. Then for each character (typically a data buffer) you pass the current CRC value and the character for which you wish to obtain a CRC from. Return Value 32 Bit CRC value. Example crc32 LONG value SHORT crc32 = 0FFFFFFFFh ! Initialize crc32 = GetCRC32(value,crc32) ! get CRC GetZmodem ----------------------------------------------------------------- Purpose Receives 1 or more files using the Zmodem Protocol. GetZmodem(port, statfunc) SHORT port COM Port Number SHORT statfunc 0 or 1 (see below) Type Function - Returns SHORT Description This function allows you to receive one or more files using Zmodem. The files will be placed in whatever directory the program happens to be in at the time of the call. You may want to use SETPATH to change into a work directory prior to the call. The statfunc parameter allows you to override the default Transfer Status Window. A value of 0 means the internal window will be displayed and updated. A value of 1 means you will open your own window and the transfer statistics will be displayed on it instead. Return Value 0 for successful transfer. If an error occurs, the following values are returned: 1 - Error opening file 4 - Time out 2 - Receiver cancelled 5 - No carrier 3 - Sender cancelled 6 - Error writing file Example error = GetZmodem(0,0) ! Receive using Zmodem IsRing ----------------------------------------------------------------- Purpose Check to see if the Phone is Ringing. IsRing(port) SHORT port COM Port Number Type Function - Returns SHORT Description This function allows you check to see if the Phone is Ringing. Return Value Returns 0 if the phone is not ringing, 1 if it is. Example port SHORT cstr CSTRING port = 0 ! Use COM 1 cstr = 'ATA' ! Answer Phone string if IsRing(0) ! is there a carrier? ComPuts(port,cstr) ! Tell Modem to Answer end LineStat ----------------------------------------------------------------- Purpose Returns UART Line Status. LineStat(port) SHORT port COM Port Number Type Function - Returns BYTE Description Returns the value of the Line Status Register. Note that the value returned is the contents of the Line Status Register at the time the last Line Status Interrupt occured. This information will tell you if there was a Receiver Overrun, Parity, or Framing error. The value is a Bit Flag. The bits have the following meanings: 1 - Overrun Error 2 - Parity Error 3 - Framing Error If a bit is on, it is set to a 1. If it is off, it is set to a 0. To test if a bit is on you use the Clarion BAND function. Return Value Bit Flag containing Line Status. Example linstat BYTE linstat = LineStat(0) ! get Line Status if BAND(linstat,02h) ! check for Overrun ! Lost some incomming data end PeekChr ----------------------------------------------------------------- Purpose Checks if character is in Receive Buffer. PeekChr(port, chr) SHORT port COM Port Number BYTE chr Character to check for Type Function - Returns SHORT Description This function checks the Receiver Buffer to see if it contains a certain character. Return Value 0 if character not in buffer, 1 if it is. Example port SHORT port = 0 ! use COM 1 if PeekChr(port,10) ! check for Line Feed ! there is a Line Feed in the Buffer end RecvCount ----------------------------------------------------------------- Purpose Gets number of characters in Receive Buffer. RecvCount(port) SHORT port COM Port Number Type Function - Returns USHORT Description This function returns the number of characters in the Receive Buffer waiting to be read. Return Value Number of characters in Receive Buffer. Example port SHORT numchrs USHORT port = 0 ! use COM 1 numchrs = RecvCount(port) ! get # of chars SendZmodem ----------------------------------------------------------------- Purpose Sends one or more files using Zmodem. SendZmodem(port, filename, statfunc) SHORT port COM Port Number CSTRING filename Name of file to upload SHORT statfunc 0 or 1 (see below) Type Function - Returns SHORT Description This function allows you to send one or more files to a remote computer using the Zmodem Protocol. Filename is a CSTRING containing the name of the file to upload. It may contain a Wild Card Specification to send more than one file at a time. The statfunc parameter allows you to override the default Transfer Status Window. A value of 0 means the internal window will be displayed and updated. A value of 1 means you will open your own window and the transfer statistics will be displayed on it instead. Return Value 0 for successful transfer. If an error occurs, the following values are returned: 1 - Error opening file 4 - Time out 2 - Receiver cancelled 5 - No carrier 3 - Sender cancelled Example cstr CSTRING(100) cstr = 'FILE.ZIP' ! send a single file SendZmodem(0,cstr,0) cstr = '*.ZIP' ! send all the ZIP files SendZmodem(0,cstr,0) SendZmodem1 ----------------------------------------------------------------- Purpose Sends one or more files using Zmodem. SendZmodem1(port, filename, path, flag, statfunc) SHORT port COM Port Number CSTRING filename Name of file to upload CSTRING path Path of file to upload SHORT flag Control Flag SHORT statfunc 0 or 1 (see below) Type Function - Returns SHORT Description This is an alternate Zmodem send function that allows you to control the file sends according to your needs. This is especially useful if you need to send more than one file and the files are not all in the same directory. Filename is a CSTRING containing the name of the file to upload. It may not be a Wild Card Specification. Path is a CSTRING containing the full path to where the file is located. It should be in the form of "C:\FILES", without a trailing slash. Flag is defined as follows: 0 = This is the First File in the Batch. >0 = This is the Second and Subsequent File. -1 = End the Batch (no more files to send). You must always end the batch with Zmodem. If you have only one file to send, you would call this function twice. If you have three files to send, you would call this function four times. Generally you call this function from within a loop where the control variable is passed as the flag parameter. After all files are sent, you then call SendZmodem1 with a flag value of -1. The statfunc parameter allows you to override the default Transfer Status Window. A value of 0 means the internal window will be displayed and updated. A value of 1 means you will open your own window and the transfer statistics will be displayed on it instead. Return Value 0 for successful transfer. If an error occurs, the following values are returned: 1 - Error opening file 4 - Time out 2 - Receiver cancelled 5 - No carrier 3 - Sender cancelled Example r SHORT fname CSTRING(100) fpath CSTRING(160) Loop r = 0 To 3 ! 4 files to send fname = Clip(files[r+1]) ! get file name fpath = Clip(filepath[r+1]) ! get file's path If SendZmodem1(port,fname,fpath,r,0) NOT= 0 Break End End r = SendZmodem1(port,fname,fpath,-1,0) ! end the Batch SetCapture ----------------------------------------------------------------- Purpose Turns Capture Buffer On or Off. SetCapture(how) SHORT how 0 = Turn Capture Buffer off 1 = Turn Capture Buffer on Type Function - Returns SHORT Description Turns automatic data capturing on or off. When the capture buffer is on, any data sent to the screen using Gputc or Gputs will also be stored in the capture buffer (ANSI sequences are stripped). The capture buffer is capable of holding 64k of data. When the buffer becomes full, it is automatically written to a disk file. Whenever you need to view the capture buffer, you should first flush the buffer to disk by calling SetCapture with a parameter of 0. Be sure to turn the buffer back on when you are ready to capture more data. Return Value 0 if memory for the buffer was successfully allocated, 1 if there is insufficient memory. Example ScrFile CSTRING(64) ! Name of ScrollBack File ! set up an automatic Scroll Back Buffer ScrFile = 'GTERM$$.CAP' ! Give Scroll File a name Do TurnOnCapture ! Turn on Capture ..... ! your program code here ! end of procedure, close Scroll Back Buffer retchr = SetCapture(0) ! Turn Capture Off Return ! Return from Procedure TurnOnCapture Routine ! Turn on Capture SetCaptureFile(ScrFile) ! Name of file if SetCapture(1) ! and turn on Capture Open(CaptureErr) ! No Memory bell() ! make noise Accept ! tell um Close(CaptureErr) ! close error screen end Exit ! Return from Routine SetCaptureFile ----------------------------------------------------------------- Purpose Names the Capture Buffer File. SetCaptureFile(filename) CSTRING filename Name to use for Capture File Type Procedure Description Names the file that will be used to store captured data. Return Value None. Example See the example for SetCapture. UpLoad ----------------------------------------------------------------- Purpose Sends one or more files. UpLoad(port, protocol, filename, statfunc) SHORT port COM Port Number SHORT protocol Number of protocol to use CSTRING filename Name of file to upload SHORT statfunc 0 or 1 (see below) Type Function - Returns SHORT Description This function allows you to send a file to a remote computer. The protocols are defined as follows: 0 = ASCII 3 = 1K Xmodem-G 1 = Xmodem 4 = Ymodem 2 = 1K Xmodem 5 = Ymodem-G Filename is a CSTRING containing the name of the file to upload. If the protocol is a batch protocol (Ymodem or Ymodem-G) then you may pass a Wild Card Specification to send more than one file at a time. The statfunc parameter allows you to override the default Transfer Status Window. A value of 0 means the internal window will be displayed and updated. A value of 1 means you will open your own window and the transfer statistics will be displayed on it instead. Return Value 0 for successful transfer. If an error occurs, the following values are returned: 1 - Error opening file 4 - Time out 2 - Receiver cancelled 5 - No carrier 3 - Sender cancelled 6 - Error reading file Example cstr CSTRING(100) cstr = 'FILE.ZIP' ! send a single file UpLoad(0,2,cstr,0) ! using 1K Xmodem cstr = '*.ZIP' ! send all the ZIP files UpLoad(0,4,cstr,0) ! using Ymodem